#pragma once

#include <i_component_container.h>
#include <i_mt_list.h>
#include "component_factory.h"


class CComponentContainer : public IComponentContainer
{
public:
	CComponentContainer(CComponentFactoryCenter& center);

	virtual err_code_t Register(IComponentHolder& holder);
	virtual void Unregister(IComponentHolder& holder);

	virtual err_code_t Start() override;
	virtual void Stop() override;
	virtual void Update() override;

	virtual void PostComponent(ComID, const CComponentCallBackFn& cb) override;

	virtual void RemoveComponent(ComID com_id) override;

	void AppendComponent(const std::string& name, const CComponentFactoryPtr& ptr);
protected:
	struct _ComponentDetail
	{
		size_t com_id = 0;
		std::string name;
		std::set<IComponentHolder*> holders;
		CComponentPtr component_ptr;
	};

	void _Install();
	void _Uninstall();

	void _Install(_ComponentDetail& detail);
	void _Uninstall(_ComponentDetail& detail);
	_ComponentDetail* _GetDetail(size_t com_id);
	_ComponentDetail& _MutableDetail(const std::string& name);
protected:
	bool m_running;
	CComponentFactoryCenter& m_center;
	std::unordered_map<std::string, size_t> m_component_detail;
	std::vector<_ComponentDetail> m_components;

	struct _ComponentMsg
	{
		ComID com_id;
		CComponentCallBackFn fn;
		_ComponentMsg(ComID id, const CComponentCallBackFn& f) : com_id(id), fn(f)
		{}
	};

	CMTList<_ComponentMsg> m_msg_list;
};
